package com.cloud.lan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloud.lan.aop.RequestClient;
import com.cloud.lan.api.dto.req.LanUserReq;
import com.cloud.lan.api.dto.req.WxLoginRequest;
import com.cloud.lan.api.dto.resp.OnLoginResp;
import com.cloud.lan.dao.LanUserMapper;
import com.cloud.lan.dao.LanUserWxMapper;
import com.cloud.lan.entity.base.BaseResponse;
import com.cloud.lan.entity.base.exceptions.BaseException;
import com.cloud.lan.entity.enums.LanError;
import com.cloud.lan.entity.enums.RedisKeyEnum;
import com.cloud.lan.entity.model.dataobject.LanUserDO;
import com.cloud.lan.entity.model.dataobject.LanUserWxDO;
import com.cloud.lan.service.ILanUserV2Service;
import com.cloud.lan.service.tx.wx.WxInitService;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import static com.cloud.lan.entity.utils.ConstantInterface.Enum.ConstantNumber.ZERO;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author xyqierkang@163.com
 * @since 2021-12-06
 */
@Slf4j
@Service
public class LanUserServiceV2Impl extends ServiceImpl<LanUserMapper, LanUserDO> implements ILanUserV2Service {

    @Resource
    WxInitService wxInitService;
    @Resource
    LanUserMapper lanUserMapper;
    @Resource
    LanUserWxMapper lanUserWxMapper;
    @Resource
    RedisService redisService;

    @Override
    @RequestClient
    public BaseResponse<OnLoginResp> onLogin(WxLoginRequest request) {
        try {
            WxMaJscode2SessionResult result = wxInitService.getSession(request.getWxAuthCode());
            String openId = result.getOpenid();
            String unionId = result.getUnionid();
            String token = result.getSessionKey();
            OnLoginResp onLoginResp = new OnLoginResp();
            LambdaQueryWrapper<LanUserDO> wxQw = new LambdaQueryWrapper<>();
            wxQw.eq(LanUserDO::getOpenId, openId);
            LanUserDO lanUserDO = lanUserMapper.selectOne(wxQw);
            Long userId = Long.parseLong(RandomUtil.randomNumbers(10));
            // 初始化 如果 LanUserWxDO没有sessionKey 新增
            LambdaQueryWrapper<LanUserWxDO> luWd = new LambdaQueryWrapper<>();
            luWd.eq(LanUserWxDO::getToken, token);
            if (lanUserWxMapper.selectCount(luWd).equals(ZERO.getKey())) {
                LanUserWxDO userWxDO = new LanUserWxDO();
                userWxDO.setToken(token).setOpenId(openId);
                lanUserWxMapper.insert(userWxDO);
            }
            onLoginResp.setSessionKey(token);
            // 判断用户是否是新用户
            if (lanUserDO == null) {
                LanUserDO userDO = new LanUserDO();
                userDO.setOpenId(openId).setUserId(userId).setUnionId(unionId);
                lanUserMapper.insert(userDO);
                return BaseResponse.success(onLoginResp);
            } else {
                LambdaUpdateWrapper<LanUserDO> luw = new LambdaUpdateWrapper<>();
                luw.set(LanUserDO::getUpdateTime, DateUtil.now());
                luw.set(LanUserDO::getUnionId, unionId);
                luw.eq(LanUserDO::getId, lanUserDO.getId());
                lanUserMapper.update(new LanUserDO(), luw);
            }
            // 校验用户是否绑定手机号
            if (StrUtil.isNotEmpty(lanUserDO.getUserPhone())) {
                onLoginResp.setAuthPhone(Boolean.FALSE);
            }
            // 校验用户是否需要微信授权 目前根据头像校验
            if (StrUtil.isNotEmpty(lanUserDO.getWxHead())) {
                onLoginResp.setAuthorize(Boolean.FALSE);
            }
            OnLoginResp.UserInfo userInfo = new OnLoginResp().new UserInfo();
            BeanUtil.copyProperties(lanUserDO, userInfo);
            onLoginResp.setUserInfo(userInfo);
            log.info("#微信认证 登录 用户信息 onLogin token {}", token);
            return BaseResponse.success(onLoginResp);
        } catch (Exception e) {
            log.error("微信认证 用户信息 异常:", e);
            return BaseResponse.error(e.getMessage());
        }
    }

    @Override
    public BaseResponse<Object> authLogin(LanUserReq request) {
        log.info("#更新 authLogin 用户信息 {}", request);
        String key = request.getToken().replaceAll(" ", "");
        //校验 验证码 短信验证
        String imgCode = redisService.get(RedisKeyEnum.IMG_CODE.key(key));
        String smsCode = redisService.get(RedisKeyEnum.SMS_CODE.key(key));
        log.info("#校验验证码 imgCode {} smsCode {} 前端接收 {}", imgCode, smsCode, request);
//        if (StrUtil.isEmpty(imgCode)) {
//            log.error("{} token {}", LanError.LAN_010002.getMsg(), request.getToken());
//            throw new BaseException(LanError.LAN_010002);
//        }
//        if (!imgCode.equals(request.getImgCode())) {
//            log.error("{} token {}", LanError.LAN_010003.getMsg(), request.getToken());
//            throw new BaseException(LanError.LAN_010003);
//        }
        if (StrUtil.isEmpty(smsCode)) {
            log.error("{} token {}", LanError.LAN_010004.getMsg(), request.getToken());
            throw new BaseException(LanError.LAN_010004);
        }
        if (!smsCode.equals(request.getSmsCode())) {
            log.error("{} token {}", LanError.LAN_010005.getMsg(), request.getToken());
            throw new BaseException(LanError.LAN_010005);
        }
        // 验证码只有一次机会
        redisService.delete(RedisKeyEnum.SMS_CODE.key(key));
        redisService.delete(RedisKeyEnum.IMG_CODE.key(key));
        LambdaQueryWrapper<LanUserWxDO> wxQw = new LambdaQueryWrapper<>();
        wxQw.eq(LanUserWxDO::getToken, request.getToken());
        LanUserWxDO lanUserWxDO = lanUserWxMapper.selectOne(wxQw);
        LanUserDO model = new LanUserDO();
        BeanUtil.copyProperties(request, model);
        model.setUpdateTime(DateUtil.date());
        lanUserMapper.update(model, new
                LambdaQueryWrapper<LanUserDO>()
                .eq(LanUserDO::getOpenId, lanUserWxDO.getOpenId()));
        return BaseResponse.success();
    }
}
